#pragma once
#include <iostream>
#include <memory>
#include <iostream>
#include <string>
#include <vector>
#include <map>
extern "C" {
#include <libavformat/avformat.h>

#include <libavcodec/avcodec.h>

#include <libavfilter/avfilter.h>

#include <libavutil/avutil.h>

#include <libavutil/log.h>

#include <libavutil/error.h>

}


// 封装FFmpeg中的AVFormatContext结构体
class AVFormatContextWrapper {
public:
    // 自定义删除器，用于释放AVFormatContext
    struct AVFormatContextDeleter {
        void operator()(AVFormatContext* ctx) const {
            avformat_close_input(&ctx);
        }
    };
    // 自定义删除器，用于释放AVCodecContext
    struct AVCodecContextDeleter {
        void operator()(AVCodecContext* ctx) const {
            avcodec_close(ctx);
            avcodec_free_context(&ctx);
        }
    };
    using AVCodecContextPtr = std::unique_ptr<AVCodecContext, AVCodecContextDeleter>;
    // 构造函数
    AVFormatContextWrapper() : ctx_(nullptr, AVFormatContextDeleter()) {}

    AVFormatContextWrapper(const AVFormatContextWrapper&) = delete;
    AVFormatContextWrapper& operator=(const AVFormatContextWrapper&) = delete;

    AVFormatContextWrapper(AVFormatContextWrapper&& other) noexcept
        : eof_(other.eof_),
        ctx_(std::move(other.ctx_)),
        name_(std::move(other.name_)),
        media_type_(std::move(other.media_type_)),
        audio_type_(std::move(other.audio_type_)),
        audio_stream_index_(other.audio_stream_index_),
        video_stream_index_(other.video_stream_index_),
        time_(other.time_) {
        other.audio_stream_index_ = -1;
        other.video_stream_index_ = -1;
        other.eof_ = false;
        other.time_ = 0;
    }

    AVFormatContextWrapper& operator=(AVFormatContextWrapper&& other) noexcept {
        if (this != &other) {
            eof_ = other.eof_;
            ctx_ = std::move(other.ctx_);
            name_ = std::move(other.name_);
            media_type_ = std::move(other.media_type_);
            audio_type_ = std::move(other.audio_type_);
            audio_stream_index_ = other.audio_stream_index_;
            video_stream_index_ = other.video_stream_index_;
            time_ = other.time_;
            other.audio_stream_index_ = -1;
            other.video_stream_index_ = -1;
            other.eof_ = false;
            other.time_ = 0;
        }
        return *this;
    }


    // 打开输入文件并初始化AVFormatContext
    bool open(const std::string& filename) {
        return open_internal(filename);
    }

    bool open() {
        std::cout <<"name_: "<<name_<<std::endl;
        return open_internal(name_);
    }
    
    void close() {
        if (ctx_) {
            auto value = ctx_.get();
            avformat_close_input(&value);//close input file and free ctx_
            ctx_ = nullptr;// use to AVFormatContextDeleter to free ctx_
        }
    }
    void reset() {
        eof_ = false;
    }
    void clear() {
        // 关闭输入文件并释放AVFormatContext资源
        close();
        // // AVFormatContext指针的智能指针，用于自动释放资源
        // 重置成员变量为初始值
        name_ = "";
        audio_type_.clear();
        media_type_.clear();
        audio_stream_index_ = -1;
        video_stream_index_ = -1;
        time_ = 0;
        eof_ = false;
    }
//    // 在类实现中添加成员函数定义
//    std::pair<int, int> find_audio_video_stream_indices() const {
//        int audio_stream_index = -1;
//        int video_stream_index = -1;

//        std::string audio_type_tmp;
//        std::string media_type_tmp;

//        if (!ctx_) {
//            std::cerr << "AVFormatContext not initialized" << std::endl;
//            std::cerr << "Filename: " << name_ << std::endl; // 打印文件名
//            return std::make_pair(audio_stream_index, video_stream_index);
//        }

//        for (unsigned int i = 0; i < ctx_->nb_streams; ++i) {
//            AVStream* stream = ctx_->streams[i];
//            if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index == -1) {
//                audio_stream_index = static_cast<int>(i);
//                const AVCodec* audio_codec = avcodec_find_decoder(stream->codecpar->codec_id);
//                if (audio_codec) {
//                    audio_type_tmp = audio_codec->name;
//            //        audio_type_ =  audio_type_tmp;
//                }
//            } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_stream_index == -1) {
//                video_stream_index = static_cast<int>(i);
//                const AVCodec* video_codec = avcodec_find_decoder(stream->codecpar->codec_id);
//                if (video_codec) {
//                    media_type_tmp = video_codec->name;
//            //        media_type_ = media_type_tmp;
//                }
//            }
//        }


//        return std::make_pair(audio_stream_index, video_stream_index);
//    }
    //create seek_frame input stream type or index and time ,and flag is AVSEEK_FLAG_BACKWARD
    bool seek_frame(int stream_index, int64_t timestamp, int flag) {
        if (ctx_) {
            return av_seek_frame(ctx_.get(), stream_index, timestamp, flag) >= 0;
        }
        return false;
    }
    bool check_stream_status() {
        if(ctx_->pb == NULL){
            std::cout << "File I/O context is not initialized." << std::endl;
            return false;
        }
        if(ctx_->nb_streams <= 0){
            std::cout << "No streams found in the file." << std::endl;
            return false;
        }
        if(audio_stream_index_ < 0){
            std::cout << "No audio stream found in the file." << std::endl;
            return false;
        }
        if(ctx_->streams[audio_stream_index_] == NULL){
            std::cout << "Audio stream is not initialized." << std::endl;
            return false;
        }
        if(ctx_->streams[audio_stream_index_]->codecpar == NULL){
            std::cout << "Audio stream codec parameters are not initialized." << std::endl;
            return false;
        }
        if(ctx_->streams[audio_stream_index_]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO){
            std::cout << "Audio stream is not an audio stream." << std::endl;
            return false;
        }
        //check video stream status
        if(video_stream_index_ < 0){
            std::cout << "No video stream found in the file." << std::endl;
            return false;
        }
        if(ctx_->streams[video_stream_index_] == NULL){
            std::cout << "Video stream is not initialized." << std::endl;
            return false;
        }
        if(ctx_->streams[video_stream_index_]->codecpar == NULL){
            std::cout << "Video stream codec parameters are not initialized." << std::endl;
            return false;
        }
        if(ctx_->streams[video_stream_index_]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO){
            std::cout << "Video stream is not a video stream." << std::endl;
            return false;
        }
        return true;
    }

    bool read_frame(AVPacket& pkt) {
        if (!eof_) {
            int ret = av_read_frame(ctx_.get(), &pkt);
            if (ret == 0) {
                // Frame read successfully
                return true;
            }
            else{
                char errbuf[AV_ERROR_MAX_STRING_SIZE];
                av_strerror(ret, errbuf, sizeof(errbuf));
                if (ret == AVERROR_EOF) {
                    // End of file reached
                    eof_ = true;
                    std::cerr << "End of file reached\n";
                } else if (ret == AVERROR(EAGAIN)) {
                    // Input is blocked, try again
                    std::cerr << "Input is blocked, try again\n";
                } else if (ret == AVERROR(EIO)) {
                    // I/O error
                    std::cerr << "I/O error\n";
                } else if (ret == AVERROR(ENOMEM)) {
                    // Out of memory
                    std::cerr << "Out of memory\n";
                } else if (ret == AVERROR(EINVAL)) {
                    // Invalid argument
                    std::cerr << "Invalid argument\n";
                } else {
                    // Other errors
                    std::cerr << "Error reading frame: " << errbuf << "\n";
                }
            }
        }
        return false;
    }

    AVCodecContextPtr open_decoder(std::int32_t stream_index) const {
        AVCodecParameters* codec_params = codec_parameters(stream_index);
        if (!codec_params) {
            return AVCodecContextPtr(nullptr);
        }

        const AVCodec* codec = avcodec_find_decoder(codec_params->codec_id);
        if (!codec) {
            std::cerr << "Failed to find decoder for stream index: " << stream_index << std::endl;
            return AVCodecContextPtr(nullptr);
        }

        AVCodecContextPtr codec_ctx(avcodec_alloc_context3(codec), AVCodecContextDeleter());
        if (!codec_ctx) {
            std::cerr << "Failed to allocate memory for AVCodecContext" << std::endl;
            return AVCodecContextPtr(nullptr);
        }

        if (avcodec_parameters_to_context(codec_ctx.get(), codec_params) < 0) {
            std::cerr << "Failed to copy codec parameters to codec context" << std::endl;
            return AVCodecContextPtr(nullptr);
        }

        if (avcodec_open2(codec_ctx.get(), codec, nullptr) < 0) {
            std::cerr << "Failed to open codec" << std::endl;
            return AVCodecContextPtr(nullptr);
        }

        return codec_ctx;
    }
    // ...

    // 获取媒体文件总时长（以秒为单位）
    int duration() const { return static_cast<int>(ctx_->duration / AV_TIME_BASE); }


    // 获取媒体文件码率（以Kbit/s为单位）
    int bit_rate() const { return static_cast<int>(ctx_->bit_rate / 1000); }

    // 获取指定流的解码器参数
    AVCodecParameters* codec_parameters(std::int32_t stream_index) const {
        return ctx_->streams[stream_index]->codecpar;
    }
    //获取AVstream
    AVStream* get_stream(std::int32_t stream_index) const {
        return ctx_->streams[stream_index];
    }
    // 
    int get_nb_streams() const {
        return ctx_->nb_streams;
    }


    // 设置和获取文件名
    void set_name(const std::string&  name) { name_ = name; }
    std::string get_name() const { return name_; }

    // 获取音频类型
    std::string get_audio_type() const { return audio_type_; }

    // 获取媒体类型
    std::string get_media_type() const { return media_type_; }
    // 获取媒体类型
    std::string get_file_status() const { return media_type_; }

    //get float time_base
    double get_audio_type_time_base_double() const { return av_q2d(ctx_->streams[audio_stream_index_]->time_base); }
    double get_video_type_time_base_double() const { return av_q2d(ctx_->streams[video_stream_index_]->time_base); }
    
    //get av_q2d(avg_frame_rate);
    double get_audio_type_avg_frame_rate() const { return av_q2d(ctx_->streams[audio_stream_index_]->avg_frame_rate); }
    double get_video_type_avg_frame_rate() const { return av_q2d(ctx_->streams[video_stream_index_]->avg_frame_rate); }

    //get frame_size
    int get_audio_frame_size() const { return ctx_->streams[audio_stream_index_]->codecpar->frame_size; }

    int get_audio_stream_index() const {
        return audio_stream_index_;
    }

    int get_video_stream_index() const {
        return video_stream_index_;
    }

//    // 设置和获取音频类型
//    void set_audio_type(std::string audio_type) { audio_type_ = audio_type; }
//    std::string get_audio_type() const { return audio_type_; }

//    // 设置和获取媒体类型
//    void set_media_type(std::string media_type) { media_type_ = media_type; }
//    std::string get_media_type() const { return media_type_; }

    // 设置和获取时间
    void set_time(std::uint8_t time) { time_ = time; }
    std::uint8_t get_time() const { return time_; }


private:
    bool open_internal(const std::string& filename) {
        auto format_ptr = ctx_.get();
        int ret = avformat_open_input(&format_ptr, filename.data(), nullptr, nullptr);
        if (ret < 0) {
            std::cerr << "Failed to open input file: " << filename << std::endl;
            return false;
        }

        // 将 ctx_ 更新为 format_ptr 的值
        ctx_.reset(format_ptr);
        av_dump_format(format_ptr, 0, filename.data(), 0);
        ret = avformat_find_stream_info(format_ptr, nullptr);
        if (ret < 0) {
            std::cerr << "Failed to find stream information" << std::endl;
            return false;
        }
        find_stream_indices_and_types(audio_stream_index_, video_stream_index_, audio_type_, media_type_);


        eof_ = false;
        return true;
    }
    void find_stream_indices_and_types(int& audio_stream_index, int& video_stream_index, std::string& audio_type, std::string& media_type) const {
        audio_stream_index = -1;
        video_stream_index = -1;

        if (!ctx_) {
            std::cerr << "AVFormatContext not initialized" << std::endl;
            std::cerr << "Filename: " << name_ << std::endl; // 打印文件名
            return;
        }

        for (unsigned int i = 0; i < ctx_->nb_streams; ++i) {
            AVStream* stream = ctx_->streams[i];
            if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index == -1) {
                audio_stream_index = static_cast<int>(i);
                const AVCodec* audio_codec = avcodec_find_decoder(stream->codecpar->codec_id);
                if (audio_codec) {
                    audio_type = audio_codec->name;
                }
            } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_stream_index == -1) {
                video_stream_index = static_cast<int>(i);
                const AVCodec* video_codec = avcodec_find_decoder(stream->codecpar->codec_id);
                if (video_codec) {
                    media_type = video_codec->name;
                }
            }
        }
    }


    bool eof_;
    // AVFormatContext指针的智能指针，用于自动释放资源
    std::unique_ptr<AVFormatContext, AVFormatContextDeleter> ctx_;

    // 文件名
    std::string name_;

    // 媒体类型
    std::string media_type_;

    // 音频类型
    std::string audio_type_;

    int audio_stream_index_;
    int video_stream_index_;


    // 时间
    std::uint8_t time_;

};
